<template>
  <div class="file-upload-container">
    <!-- 文件上传区域 -->
    <div 
      class="upload-area"
      :class="{ 'drag-over': isDragOver, 'uploading': isUploading }"
      @drop="handleDrop"
      @dragover.prevent="handleDragOver"
      @dragleave="handleDragLeave"
      @click="triggerFileInput"
    >
      <input 
        ref="fileInput"
        type="file"
        :multiple="multiple"
        :accept="acceptedTypes"
        @change="handleFileSelect"
        class="hidden"
      />
      
      <div v-if="!isUploading" class="upload-content">
        <svg class="upload-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"></path>
        </svg>
        <p class="upload-text">点击或拖拽文件到此处上传</p>
        <p class="upload-hint">支持格式: {{ acceptedTypesText }}</p>
        <p class="upload-limit">最大文件大小: {{ maxSizeText }}</p>
      </div>
      
      <div v-else class="upload-progress">
        <div class="progress-bar">
          <div class="progress-fill" :style="{ width: uploadProgress + '%' }"></div>
        </div>
        <p class="progress-text">上传中... {{ uploadProgress }}%</p>
      </div>
    </div>
    
    <!-- 错误信息 -->
    <div v-if="error" class="error-message">
      <svg class="error-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
              d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
      </svg>
      <span>{{ error }}</span>
    </div>
    
    <!-- 已上传文件列表 -->
    <div v-if="uploadedFiles.length > 0" class="uploaded-files">
      <h4 class="files-title">已上传文件</h4>
      <div class="file-list">
        <div v-for="file in uploadedFiles" :key="file.filename" class="file-item">
          <div class="file-info">
            <svg class="file-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                    d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
            </svg>
            <div class="file-details">
              <span class="file-name">{{ file.originalName }}</span>
            </div>
          </div>
          <div class="file-actions">
            <a :href="file.url" target="_blank" class="view-btn">
              <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                      d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                      d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path>
              </svg>
            </a>
            <button @click="deleteFile(file)" class="delete-btn">
              <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                      d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path>
              </svg>
            </button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { useAuthStore } from '@/stores/auth'

// 从环境变量读取API基础地址
const API_BASE_URL = `http://${import.meta.env.VITE_BACKEND_HOST}:${import.meta.env.VITE_BACKEND_PORT}`

interface UploadedFile {
  filename: string
  originalName: string
  size: number
  url: string
  path: string
}

interface Props {
  chapterNumber: number
  materialType: string
  multiple?: boolean
  maxSize?: number // MB
  initialFiles?: UploadedFile[] // 初始文件列表
}

const props = withDefaults(defineProps<Props>(), {
  multiple: true,
  maxSize: 100,
  initialFiles: () => []
})

const emit = defineEmits<{
  'files-uploaded': [files: UploadedFile[]]
  'file-deleted': [fileName: string]
}>()

const authStore = useAuthStore()
const fileInput = ref<HTMLInputElement>()
const isDragOver = ref(false)
const isUploading = ref(false)
const uploadProgress = ref(0)
const error = ref('')
const uploadedFiles = ref<UploadedFile[]>([])

// 根据材料类型定义接受的文件类型
const acceptedTypes = computed(() => {
  const typeMap: Record<string, string> = {
    lecture: '.doc,.docx',
    slides: '.pptx,.pdf',
    docx: '.doc,.docx',
    pptx: '.pptx,.pdf',
    video: '.mp4,.avi,.mov,.wmv,.flv,.webm',
    examples: '.html,.css,.js,.vue,.zip,.rar',
    practice: '.html,.css,.js,.vue,.zip,.rar,.md',
    assignment: '.pdf,.doc,.docx,.md,.txt'
  }
  return typeMap[props.materialType] || '*'
})

const acceptedTypesText = computed(() => {
  return acceptedTypes.value.replace(/\./g, '').toUpperCase()
})

const maxSizeText = computed(() => {
  return `${props.maxSize}MB`
})

// 触发文件选择
const triggerFileInput = () => {
  if (!isUploading.value) {
    fileInput.value?.click()
  }
}

// 处理拖拽
const handleDragOver = (e: DragEvent) => {
  e.preventDefault()
  isDragOver.value = true
}

const handleDragLeave = () => {
  isDragOver.value = false
}

const handleDrop = (e: DragEvent) => {
  e.preventDefault()
  isDragOver.value = false
  
  const files = Array.from(e.dataTransfer?.files || [])
  if (files.length > 0) {
    uploadFiles(files)
  }
}

// 处理文件选择
const handleFileSelect = (e: Event) => {
  const target = e.target as HTMLInputElement
  const files = Array.from(target.files || [])
  if (files.length > 0) {
    uploadFiles(files)
  }
}

// 验证文件
const validateFile = (file: File): string | null => {
  // 检查文件大小
  if (file.size > props.maxSize * 1024 * 1024) {
    return `文件 ${file.name} 超过最大大小限制 ${props.maxSize}MB`
  }
  
  // 检查文件类型
  const ext = '.' + file.name.split('.').pop()?.toLowerCase()
  if (acceptedTypes.value !== '*' && !acceptedTypes.value.includes(ext)) {
    return `文件 ${file.name} 格式不支持`
  }
  
  return null
}

// 上传文件
const uploadFiles = async (files: File[]) => {
  error.value = ''
  
  // 验证所有文件
  for (const file of files) {
    const validationError = validateFile(file)
    if (validationError) {
      error.value = validationError
      return
    }
  }
  
  isUploading.value = true
  uploadProgress.value = 0
  
  try {
    const formData = new FormData()
    
    if (props.multiple) {
      files.forEach(file => {
        formData.append('files', file)
      })
    } else {
      formData.append('file', files[0])
    }
    
    formData.append('chapterNumber', props.chapterNumber.toString())
    formData.append('materialType', props.materialType)
    
    const endpoint = props.multiple ? '/upload-multiple' : '/upload'
    
    const response = await fetch(`${API_BASE_URL}/api/file${endpoint}`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${authStore.token}`
      },
      body: formData
    })
    
    if (!response.ok) {
      const errorData = await response.json()
      throw new Error(errorData.message || '上传失败')
    }
    
    const result = await response.json()
    const newFiles = Array.isArray(result.data) ? result.data : [result.data]
    
    uploadedFiles.value.push(...newFiles)
    emit('files-uploaded', newFiles)
    
    uploadProgress.value = 100
    
    // 重置文件输入
    if (fileInput.value) {
      fileInput.value.value = ''
    }
  } catch (err) {
    error.value = err instanceof Error ? err.message : '上传失败'
  } finally {
    setTimeout(() => {
      isUploading.value = false
      uploadProgress.value = 0
    }, 1000)
  }
}

// 删除文件
const deleteFile = async (file: UploadedFile) => {
  if (!confirm(`确定要删除文件 ${file.originalName} 吗？`)) {
    return
  }
  
  try {
    const response = await fetch(
      `${API_BASE_URL}/api/file/files/${props.chapterNumber}/${props.materialType}/${file.filename}`,
      {
        method: 'DELETE',
        headers: {
          'Authorization': `Bearer ${authStore.token}`
        }
      }
    )
    
    if (!response.ok) {
      const errorData = await response.json()
      throw new Error(errorData.message || '删除失败')
    }
    
    const index = uploadedFiles.value.findIndex(f => f.filename === file.filename)
    if (index > -1) {
      uploadedFiles.value.splice(index, 1)
    }
    
    emit('file-deleted', file.filename)
  } catch (err) {
    error.value = err instanceof Error ? err.message : '删除失败'
  }
}

// 格式化文件大小
const formatFileSize = (bytes: number): string => {
  if (bytes === 0) return '0 Bytes'
  const k = 1024
  const sizes = ['Bytes', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

// 加载已存在的文件
const loadExistingFiles = async () => {
  try {
    const response = await fetch(
      `${API_BASE_URL}/api/file/files/${props.chapterNumber}/${props.materialType}`,
      {
        headers: {
          'Authorization': `Bearer ${authStore.token}`
        }
      }
    )
    
    if (response.ok) {
      const result = await response.json()
      uploadedFiles.value = result.data || []
    }
  } catch (err) {
    console.error('加载文件列表失败:', err)
  }
}

// 组件挂载时加载文件
onMounted(() => {
  // 如果有初始文件列表，使用初始文件；否则从API加载
  if (props.initialFiles && props.initialFiles.length > 0) {
    uploadedFiles.value = [...props.initialFiles]
  } else {
    loadExistingFiles()
  }
})
</script>

<style scoped>
.file-upload-container {
  @apply space-y-4;
}

.upload-area {
  @apply border-2 border-dashed border-gray-300 rounded-lg p-8 text-center cursor-pointer transition-all duration-200;
}

.upload-area:hover {
  @apply border-blue-400 bg-blue-50;
}

.upload-area.drag-over {
  @apply border-blue-500 bg-blue-100;
}

.upload-area.uploading {
  @apply cursor-not-allowed bg-gray-50;
}

.upload-content {
  @apply space-y-2;
}

.upload-icon {
  @apply w-12 h-12 mx-auto text-gray-400;
}

.upload-text {
  @apply text-lg font-medium text-gray-700;
}

.upload-hint {
  @apply text-sm text-gray-500;
}

.upload-limit {
  @apply text-xs text-gray-400;
}

.upload-progress {
  @apply space-y-4;
}

.progress-bar {
  @apply w-full bg-gray-200 rounded-full h-2;
}

.progress-fill {
  @apply bg-blue-600 h-2 rounded-full transition-all duration-300;
}

.progress-text {
  @apply text-sm text-gray-600;
}

.error-message {
  @apply flex items-center space-x-2 p-3 bg-red-50 border border-red-200 rounded-lg text-red-700;
}

.error-icon {
  @apply w-5 h-5 text-red-500;
}

.uploaded-files {
  @apply space-y-3;
}

.files-title {
  @apply text-sm font-medium text-gray-700;
}

.file-list {
  @apply space-y-2;
}

.file-item {
  @apply flex items-center justify-between p-3 bg-gray-50 rounded-lg;
}

.file-info {
  @apply flex items-center space-x-3;
}

.file-icon {
  @apply w-5 h-5 text-gray-500;
}

.file-details {
  @apply flex flex-col;
}

.file-name {
  @apply text-sm font-medium text-gray-900;
}

.file-size {
  @apply text-xs text-gray-500;
}

.file-actions {
  @apply flex items-center space-x-2;
}

.view-btn {
  @apply p-1 text-blue-600 hover:text-blue-800 transition-colors;
}

.delete-btn {
  @apply p-1 text-red-600 hover:text-red-800 transition-colors;
}

.hidden {
  @apply sr-only;
}
</style>